#ifndef COMPONENTFACTORY_H
#define COMPONENTFACTORY_H

#include <string>
#include <map>

//#include "Component.h"

using namespace std;

class Component;
class ComponentContainer;


/**
 * \class IComponentCreator
 * \author gershon
 * \date 07/28/2010
 * \file ComponentFactory.h
 * \brief 
 */
struct IComponentCreator
{
	virtual Component* operator()(ComponentContainer* owner, const string &name) = 0;
	virtual ~IComponentCreator() {}
};

typedef std::map<std::string, IComponentCreator*> ComponentCreatorMap;

template<class T>
/**
 * \class ComponentCreator
 * \author gershon
 * \date 07/28/2010
 * \file ComponentFactory.h
 * \brief 
 */
struct ComponentCreator : public IComponentCreator
{
	Component* operator()(ComponentContainer* owner, const std::string &name)
	{
		return new T(owner, name);
	}
};

class ComponentFactoryException: public std::exception
{
public:
	ComponentFactoryException(std::string s) : msg(s) {}
	ComponentFactoryException() throw() { }
	virtual ~ComponentFactoryException() throw() {}
	virtual const char* what() const throw()
	{
		return msg.c_str();
	}
	std::string msg;
};


/**
 * \class ComponentFactory
 * \author gershon
 * \date 07/26/2010
 * \file ComponentFactory.h
 * \brief Factory Pattern class for component registration
 */
class ComponentFactory
{
	static ComponentFactory* ms_instance;

public:
	// Dynamically allocated map
	ComponentCreatorMap* creators;

	static ComponentFactory* getSingletonPtr();
	static ComponentFactory& getSingleton();
	static void Release();

	
	// Push a creator to map
	void Register(const std::string &type, IComponentCreator* functor);
	Component* Create(ComponentContainer* owner, const std::string &compType, const std::string &compName="");


private:
	ComponentFactory();
	virtual ~ComponentFactory();

};

#endif // COMPONENTFACTORY_H
